/*
 * Quercia Luciano
 * Algoritmi e Strutture Dati
 * a.a. 2009-10
 */


#ifndef _PILA_H_
#define _PILA_H_


#include "nodoP.h"

template <class T>
class Pila
{
public:
	Pila();
	~Pila();

	//operatori
	bool pilaVuota() const;
	void inPila(T elem);
	void fuoriPila()             throw (char const *);
	T leggiPila() const         throw (char const *);

	//metodi personalizzati
	void print(void);
	void printAll(void);

private:
	int nNodi;
	typedef NodoP<T> * posizione;
	posizione top;
};



/*****************************
 *        DEFINIZIONI        *
 *     dei metodi di Pila    *
 *****************************/


template <class T>
Pila<T>::Pila()
{
	top = NULL ;
	nNodi = 0 ;
}



template <class T>
Pila<T>::~Pila() {
	while ( !pilaVuota() )
		fuoriPila();
}



template <class T>
bool Pila<T>::pilaVuota() const {
	if ( nNodi == 0 )
		return true;
	else
		return false;
}



template <class T>
void Pila<T>::inPila(T elem) {
	NodoP<T> *temp= new NodoP<T>;

	temp->setValue( elem ) ;

	temp->setLink( top );
	top = temp ;
	nNodi++ ;
}


template <class T>
void Pila<T>::fuoriPila() throw (char const *) {
	if ( !pilaVuota() ) {
		NodoP<T> *temp= new NodoP<T> ;
		temp = top;
		top = top->getLink() ;
		delete temp;
		nNodi-- ;
	}
	else
		throw "Impossibile cancellare da una Lista vuota." ;
}


template <class T>
T Pila<T>::leggiPila() const throw (char const *) {
	if ( !pilaVuota() )
		return top->getValue() ;
	else
		throw "Impossibile leggere da una Pila vuota." ;
}




template <class T>
void Pila<T>::print(void) {
	if ( ! pilaVuota() ) {
		cout << "[ " << leggiPila() << " ]" << endl ;
	} else
		cout << "[ Empty Stack ]" << endl ;
}


template <class T>
void Pila<T>::printAll(void) {
	if ( ! pilaVuota() ) {
		cout << "[ " ;

		posizione p;
		p = top;
		for (int i = 0; i<nNodi; i++) {
			cout << p->getValue() << " " ;
			p = p->getLink();
		}

		cout << "]" << endl ;
	} else
		cout << "[ Empty Stack ]" << endl ;
}

#endif
